#pragma once 

#include "Conn.h"
#include "Worker.h"
#include "Service.h"
#include "SocketWorker.h"

#include <vector>
#include <unordered_map>
using namespace std;

class Sunnet {
public:
    Sunnet();
    ~Sunnet(); 
    shared_ptr<BaseMsg> MakeMsg(uint32_t source, char *buff, int len);
public:
    static Sunnet* instance; // 单例

public:
    void Start(); // 初始化并开始
    void Wait();  // 等待运行
private:
    void StartWorker(); // 开启工作线程

// ---------------- global -------------------- //
public:
    void Send(uint32_t toId, shared_ptr<BaseMsg> msg); // 发送消息
    void PushGlobalQueue(shared_ptr<Service> srv);     // 全局队列插入服务
    shared_ptr<Service> PopGlobalQueue();              // 全局队列弹出服务
    
private:
    queue<shared_ptr<Service>> globalQueue;
    int globalLength; 
    pthread_spinlock_t globalLock;

// ---------------- worker -------------------- //
private:
    int WORKER_NUM = 8;      // 工作线程数
    vector<Worker*> workers; // worker对象
    vector<thread*> workerThreads; // 线程

// ---------------- socket worker -------------------- //
public:
    void StartSocket();        // 开启网络线程 
    int Listen(uint32_t port, uint32_t serviceId); // 网络监听
    void CloseConn(uint32_t fd);
    // 开放一个修改epoll中fd事件的方法
    void ModifyEvent(uint32_t fd, bool epollOut);
private:
    SocketWorker* socketWorker;// 网络worker对象
    thread* socketThread;      // 网络线程

// ---------------- service -------------------- //
public:
    unordered_map<uint32_t, shared_ptr<Service>> services; // 服务列表
    uint32_t maxId = 0; // 服务最大ID
    pthread_rwlock_t servicesLock; // 读写锁
public:
    uint32_t NewService(shared_ptr<string> type); // 创建服务
    void KillService(uint32_t id); // 删除服务
private:
    shared_ptr<Service> GetService(uint32_t id);

// ---------------- condition -------------------- //
public:
    void CheckAndWeakUp(); // 唤醒工作线程
    void WorkerWait();     // 工作线程等待
private:
    pthread_mutex_t sleepMtx;
    pthread_cond_t sleepCond;
    int sleepCount = 0;      // 休眠工作线程数

// ---------------- connect -------------------- //
public:
    int AddConn(int fd, uint32_t id, Conn::TYPE type);
    shared_ptr<Conn> GetConn(int fd);
    bool RemoveConn(int fd);
private:
    unordered_map<uint32_t, shared_ptr<Conn>> conns;
    pthread_rwlock_t connsLock;
};